﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3D = Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;


namespace CubePuzzle
{
    public class DxAppMenu : DxApp
    {
        private MatrixBuilder mb;
        private int state;

        public int State
        {
            set
            {
                state = value;
            }
            get
            {
                return state;
            }
        }

        public override void ReadKeyBoard()
        {
            
        }

        public override void ReadMouse()
        {
            
        }

        public override void UpdateCamera()
        {
            
        }

        public override void SetUpCamera()
        {
            cameraPosition = new Vector3(0, mb.K*mb.N, mb.K*mb.N*2);

            cameraForward = new Vector3(0, 0, -1);

            cameraAt = new Vector3(0, mb.K * mb.N, 0);

            cameraUpVector = new Vector3(0, 1, 0);

            cameraDistance = mb.K * mb.N * 2;

            matProjection = Matrix.PerspectiveFovLH((float)Math.PI / 3, (float)form.PbMenu.Width / (float)form.PbMenu.Height, 1f, 100f);

            matView = Matrix.LookAtLH(cameraPosition, cameraAt, cameraUpVector);

            matWorld = Matrix.Identity;

            device.Transform.Projection = matProjection;
            device.Transform.View = matView;
            device.Transform.World = matWorld;
        }

        public void drawItem()
        {
            for (int i = 0; i < mb.K; i++)
            {
                if (state == 0)
                    effect.SetValue("xColoredTexture", cubeTextures[(i + 1)% 11]);
                else
                    if ((i + 1) != state)
                        effect.SetValue("xColoredTexture", cubeTextures[0]);
                    else
                        effect.SetValue("xColoredTexture", cubeTextures[(i + 1) % 11]);

                for (int ii = 0; ii < mb.N; ii++)
                {
                    for (int jj = 0; jj < mb.N; jj++)
                    {
                        for (int kk = 0; kk < mb.N; kk++)
                        {
                            if (mb.Items[i].getItem(ii, jj, kk) > 0)
                            {
                                if ((state == i + 1) || (state == 0))
                                {
                                    Matrix matRotTemp = Matrix.RotationY(((float)Math.PI) * 2 * ((float)(Environment.TickCount % 10000) / 10000));
                                    if (state == 0) matWorld = Matrix.Translation(ii, jj + (2 * i * mb.N), kk) * matRotTemp;
                                    else matWorld = Matrix.Translation(ii, jj + (2 * i * mb.N), kk) * matRotTemp;
                                    effect.SetValue("xWorldViewProjection", matWorld * matView * matProjection);
                                    effect.SetValue("xRot", matRotTemp);
                                }
                                else
                                {
                                    matWorld = Matrix.Translation(ii, jj + (2 * i * mb.N), kk);
                                    effect.SetValue("xWorldViewProjection", matWorld * matView * matProjection);
                                    effect.SetValue("xRot", Matrix.Identity);
                                }

                                effect.CommitChanges();
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 4, 2);
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 8, 2);
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 12, 2);
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 16, 2);
                                device.DrawPrimitives(PrimitiveType.TriangleFan, 20, 2);
                            }
                        }
                    }
                }
            }
        }

        public override void InitTextures()
        {
            cubeTextures = new Texture[11];

            for (int i = 0; i < 11; i++)
            {
                cubeTextures[i] = TextureLoader.FromFile(device, "textures\\" + i.ToString() + ".bmp");
            }
        }

        public override void Render()
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.LightSkyBlue, 1.0f, 0);
            device.BeginScene();

            device.SetStreamSource(0, vb, 0);
            device.VertexDeclaration = vd;

            effect.Technique = "Simplest";
            effect.SetValue("xLightPos", new Vector4(cameraPosition.X, cameraPosition.Y, cameraPosition.Z, 1));
            effect.SetValue("xLightPower", 2.0f);

            int numpasses = effect.Begin(0);
            for (int i = 0; i < numpasses; i++)
            {
                effect.BeginPass(i);
                drawItem();
                effect.EndPass();
            }
            effect.End();

            // End the scene
            device.EndScene();
            device.Present();
            form.Invalidate();
        }

        public override void HandleDeviceReset(object sender, EventArgs e)
        {
            device.RenderState.CullMode = Cull.None;
            FillResources();
        }

        public DxAppMenu(IntPtr handle, Game form, MatrixBuilder mb) {
            this.mb = mb;
            this.form = form;
            InitializeDevice(handle);
            AllocateResources();
            FillResources();
            InitializeKeyboard();
            InitializeMouse();
            InitTextures();
        }
    }
}
